﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ObligatorioBD.MerObjects;
using System.Windows.Forms;

namespace ObligatorioBD.Logic
{
    class Normalize
    {
        public Normalize()
        {
            DatabaseInterface.Connection conn = new DatabaseInterface.Connection();    
        }

        public Mer Form1 (Mer mer) 
        {
            mer = Relaciones(mer);
            mer = Multivaluados(mer);
            mer = Compuestos(mer);
            mer = Cardinalidades(mer);
            MessageBox.Show("Mer: " + mer.Name + " normalizado con éxito!");
            return mer;
        }

        private Mer Multivaluados(Mer mer) 
        {
            List<Entity> entities = new List<Entity>();
            foreach (Entity e in mer.GetEntities()) 
            {
                List<Atribute> atributeDelete = new List<Atribute>();
                foreach (Atribute a in e.GetAtributes())
                {
                    if (a.Cantidad > 1)
                    {
                        Entity e2 = new Entity(a.Name, true);
                        foreach (Atribute atributo in e.GetAtributes())
                        {
                            if (atributo.IsPrimaryKey)
                            {
                                e2.AddAtribute(atributo);
                            }
                        }
                        a.IsPrimaryKey = true;
                        e2.AddAtribute(a);
                        atributeDelete.Add(a);
                        Relationship r = new Relationship(e.Name + "_" + a.Name);
                        r.AddEntity(e2, "N");
                        r.AddEntity(e, "1");
                        mer.AddRelation(r);
                        entities.Add(e2);
                    }
                }
                foreach (Atribute atribute in atributeDelete)
                {
                    e.RemoveAtribute(atribute);
                }
            }
            foreach (Entity entity in entities)
            {
                mer.AddEntity(entity);
            }
            return mer;
        }

        private Mer Compuestos(Mer mer)
        {
            List<Atribute> delete = new List<Atribute>();
            List<Atribute> add = new List<Atribute>();
            foreach(Entity e in mer.GetEntities())
            {
                delete.Clear();
                add.Clear();
                foreach (Atribute a in e.GetAtributes())
                {
                    if (a.HasAtributes())
                    {
                        foreach (Atribute a2 in a.GetAtributes())
                        {
                            add.Add(a2);
                        }
                        delete.Add(a);
                    }
                }
                foreach (Atribute d in delete)
                {
                    e.RemoveAtribute(d);
                }
                foreach (Atribute ad in add)
                {
                    e.AddAtribute(ad);
                }
            }
            return mer;
        }

        private Mer Cardinalidades(Mer mer) 
        {
            //Se toman solo relaciones de 2 entidades
            List<Relationship> relations = new List<Relationship>();
            List<Relationship> relationsDelete = new List<Relationship>();
            List<Atribute> atributes = new List<Atribute>();
            foreach (Relationship r in mer.GetRelations()) 
            {
                int cont = 0;
                String entity="";
                foreach (CardinalEntity e in r.GetEntities()) 
                {
                    if (e.Cardinality.Equals("N")) 
                    {
                        cont++;
                        entity = entity + e.Entity.Name + "_";
                    }
                }
                entity = entity.Remove(entity.Length - 1);
                if (cont > 1) 
                {
                    //Es una relacion N-N.
                    relationsDelete.Add(r);
                    Entity e1 = new Entity(entity, true);
                    foreach (CardinalEntity e in r.GetEntities())
                    {
                        if (e.Cardinality.Equals("N"))
                        {
                            Relationship r1 = new Relationship(e.Entity.Name + "-" + entity);
                            r1.AddEntity(e.Entity, "1");
                            r1.AddEntity(e1, "N");
                            relations.Add(r1);
                            foreach (Atribute a in e.Entity.GetAtributes())
                            {
                                if (a.IsPrimaryKey) 
                                {
                                    e1.AddAtribute(a);
                                }
                            }
                        }
                    }
                    mer.AddEntity(e1);
                }
            }
            foreach (Relationship relation in relations) 
            {
                mer.AddRelation(relation);
            }
            foreach (Relationship deleted in relationsDelete)
            {
                mer.DeteleRelation(deleted);
            }
            return mer;
        }

        private Mer Relaciones(Mer mer) 
        {
            Boolean verifica;
            List<Relationship> relationsDelete = new List<Relationship>();
            List<Relationship> relations = new List<Relationship>();
            foreach (Relationship r in mer.GetRelations())
            {
                if (r.GetAtributes().Count > 0) 
                {
                    relationsDelete.Add(r);
                    Entity e1 = new Entity(r.Name, true);
                    foreach (Atribute atribute in r.GetAtributes())
                    {
                        e1.AddAtribute(atribute);
                    }
                    foreach (CardinalEntity e in r.GetEntities())
                    {
                        Relationship r1 = new Relationship(e.Entity.Name + "-" + r.Name);
                        r1.AddEntity(e.Entity, "1");
                        r1.AddEntity(e1, "N");
                        relations.Add(r1);
                        foreach (Atribute a in e.Entity.GetAtributes())
                        {
                            if ((a.IsPrimaryKey) && (!e1.Contains(a.Name)))
                            {
                                e1.AddAtribute(a);
                            }
                        }
                    }
                    mer.AddEntity(e1);
                }
            }
            foreach (Relationship relation in relations)
            {
                mer.AddRelation(relation);
            }
            foreach (Relationship relation in relationsDelete)
            {
                mer.DeteleRelation(relation);
            }
            return mer;
        }
    }
}
